package xs.szw.service.config;

import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import xs.szw.service.filter.JwtAuthFilter;
import xs.szw.service.handler.AccessDeniedHandlerImpl;
import xs.szw.service.handler.AuthenticationEntryPointImpl;

import static org.springframework.security.config.Customizer.withDefaults;

/**
 * @program: My_SpringSecurity
 * @description: springSecurityConfig
 * @author: Songzw
 * @create: 2025-01-28 16:58
 **/
@Configuration
@EnableWebSecurity // 启用 Spring Security 的 Web 安全功能，允许配置安全过滤链
@EnableMethodSecurity // 启用方法级别的安全控制（如 @PreAuthorize 等）
@RequiredArgsConstructor
public class SecurityConfig {
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }


    private final AuthenticationEntryPointImpl authenticationEntryPoint;


    private final AccessDeniedHandlerImpl accessDeniedHandler;


    private final JwtAuthFilter jwtAuthFilter;


    private String[] ignoreUrls = new String[]{
            "/sys/captcha","/v3/api-docs/**","/swagger-ui/**",
    };

    /**
     * 配置 Spring Security 的核心过滤器链
     *
     * @param http HttpSecurity 对象，用于构建安全配置
     * @return 安全过滤器链实例
     * @throws Exception 配置过程中可能抛出的异常
     */
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                // 禁用 CSRF 保护（适用于无状态 RESTful API，使用 JWT 无需 CSRF）
                .csrf(AbstractHttpConfigurer::disable)
                // 配置请求授权规则
                .authorizeHttpRequests(auth -> auth
                        //匿名可以访问即没有登录
//                        .requestMatchers("/sys/captcha").anonymous()
                        // 所有可访问认证相关接口（如登录、注册）
                        .requestMatchers(ignoreUrls).permitAll()
                        // 管理员接口需具备 ADMIN 角色（角色名会自动添加 ROLE_ 前缀）
//                        .requestMatchers("/hello1").hasAuthority("system:test:list")
                        // 其他所有请求需认证后才能访问
                        .anyRequest().authenticated()
                )
                // 配置会话管理为无状态（JWT 方案不需要 Session）
                .sessionManagement(session -> session
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                )
//                .formLogin(AbstractHttpConfigurer::disable)
                .formLogin(formLogin ->
                        formLogin
                                .loginPage("/sys/login") // 自定义登录页面的URL
                                .loginProcessingUrl("/login") // 处理登录表单提交的URL
//                                .defaultSuccessUrl("/") // 登录成功后的默认重定向URL
                                .permitAll() // 允许所有人访问登录相关的URL
                                )
                //禁用springSecurity自带的/logout接口
                .logout(AbstractHttpConfigurer::disable)
        //配置异常认证、授权处理
                .exceptionHandling(e-> e.authenticationEntryPoint(authenticationEntryPoint).accessDeniedHandler(accessDeniedHandler))
                // 添加 JWT 认证过滤器到用户名密码认证过滤器之前
                .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
        // 启用默认跨域支持
        http.cors(withDefaults());
        return http.build();
    }

    /**
     * 用于配置不需要认证的 URI 地址
     */
    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> {
            web.ignoring().requestMatchers(
                    "/v3/api-docs/**",
                    "/swagger-ui/**",
                    "/swagger-ui.html",
                    "/webjars/**",
                    "/doc.html"
            );
        };
    }


    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

}
